import datetime
import pymongo
import Core.MongoDB as MongoDB
import Core.Gadget as Gadget
import Core.Algorithm as Algo
import Core.IO as IO
import Core.DataSeries as DataSeries
import math
import copy
from Factors.General import *
from Factors.Price import *
from sklearn import linear_model

# 尝试导入annualvolatility因子入库


database = MongoDB.MongoDB("10.13.38.41", "27017")
'''
datetiem1 = datetime.datetime(2013, 1, 1)
datetiem1 = Gadget.ToUTCDateTime(datetiem1)
datetiem2 = datetime.datetime(2017, 5, 1)
datetiem2 = Gadget.ToUTCDateTime(datetiem2)
dfBars = IO.LoadBarsAsDataFrame(database, symbol="000001.SZ",
                                    datetime1=datetiem1, datetime2=datetiem2,
                                    fields=["BClose"])
rangeBegin = dfBars.loc[0, "DateTime"]
rangeEnd = dfBars.loc[len(dfBars) - 1, "DateTime"]
dfBenchmark = IO.LoadBarsAsDataFrame(database, symbol="000001.SH",
                                         datetime1=datetiem1, datetime2=datetiem2,
                                         fields=["Close"], databaseName="Index")
dfCombine = pd.merge(dfBenchmark, dfBars, on='DateTime', how='outer')
dfCombine.fillna(method='pad', inplace=True)
factorName = "DailyReturn"
dfCombine[factorName] = dfCombine["BClose"] / dfCombine["BClose"].shift(1) - 1
factorName2 = "DailyLogReturn"
dfCombine[factorName2] = np.log(dfCombine["BClose"] / dfCombine["BClose"].shift(1))
dfCombine['AnnualVolatility'] = dfCombine['DailyReturn'].rolling(245).std()*np.sqrt(245)
print (dfCombine)
'''
period = ANNULIZED_FACTOR
sqrtPeriod = math.sqrt(period)
datetime1 = datetime.datetime(2010, 1, 1)
datetime1 = Gadget.ToUTCDateTime(datetime1)
datetime2 = datetime.datetime(2017, 5, 1)
datetime2 = Gadget.ToUTCDateTime(datetime2)
instruments = database.find("Instruments", "Stock", datetime1,datetime2)

for instrument in instruments:
    symbol = instrument["Symbol"]
    print (symbol)

    dfCombine = CalcReturnCallback(database, symbol, datetiem1 = datetime1, datetiem2 = datetime2, factorName = 'DailyReturn')
    dfCombine = dfCombine.dropna()
    length = len(dfCombine)
    # print(dfStock.head())
    if len(dfCombine) == 0:
        print("No Return Factor for" + symbol)
        continue
    # ---新股，数据不足的情况---
    if len(dfCombine) < period:
        print("Not Enough Data to Calc " + symbol)
        continue

    annualvolDataSeries = DataSeries.DataSeries(symbol + "_AnnualVolatility_Factor")

    for i in range(period - 1, len(dfCombine)):
        # ---准备数据---
        stdDateTime = dfCombine.at[i, "StdDateTime"]
        #stdDateTime = stdDateTime.tz_localize("Asia/Shanghai")

        slice = dfCombine[i - (period - 1):i + 1]
        DailyReturn = slice["DailyReturn"].std()*sqrtPeriod

        annualvolDataSeries.Add(GenarateDocument(symbol, stdDateTime, DailyReturn))
        pass
    database.saveDataSeries(annualvolDataSeries)
    pass

'''
def CalcReturnCallback(database, symbol, datetiem1, datetiem2, factorName):

    #
    dfBars = IO.LoadBarsAsDataFrame(database, symbol=symbol,
                                    datetime1=datetiem1, datetime2=datetiem2,
                                    fields=["BClose"])

    # Might be Index
    if len(dfBars) == 0:
        dfBars = IO.LoadBarsAsDataFrame(database, symbol=symbol,
                                    datetime1=datetiem1, datetime2=datetiem2,
                                    fields=["Close"],databaseName="Index")
        dfBars.rename(columns={'Close': "BClose"}, inplace=True)

    # neither Stock or Index
    if len(dfBars) == 0:
        return pd.DataFrame()

    #
    #print(dfBars.head())
    rangeBegin = dfBars.loc[0, "StdDateTime"]
    rangeEnd = dfBars.loc[len(dfBars) - 1, "StdDateTime"]
    #

    dfBenchmark = IO.LoadBarsAsDataFrame(database, symbol="000001.SH",
                                         datetime1=rangeBegin, datetime2=rangeEnd,
                                         fields=["Close"], databaseName="Index")

    dfCombine = pd.merge(dfBenchmark, dfBars, on='StdDateTime', how='outer')
    #
    dfCombine.fillna(method='pad', inplace=True)
    #
    if factorName == "DailyReturn":
        dfCombine[factorName] = dfCombine["BClose"] / dfCombine["BClose"].shift(1) - 1
    elif factorName == "DailyLogReturn":
        dfCombine[factorName] = np.log(dfCombine["BClose"] / dfCombine["BClose"].shift(1))

    return dfCombine
'''
